<template>
    <div class="ios-scroll" ref="scrollWrapper">
        <div class="scroll-content" :style="scrollStyle">
            <!-- 下拉刷新区域 -->
            <div class="pull-down" :class="{ active: isPullingDown }">
                <div class="pull-down-refresh">
                    <i :class="[pullDownIcon, { loading: isRefreshing }]"></i>
                </div>
                <div>{{ pullDownText }}</div>
            </div>

            <!-- 滚动内容 -->
            <slot></slot>

            <!-- 上拉加载区域 -->
            <div class="pull-up" v-if="enablePullUp">
                <div>{{ pullUpText }}</div>
                <div class="pull-up-refresh">
                    <i class="fas fa-sync-alt" :class="{ loading: isLoadingMore }"></i>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import BScroll from 'better-scroll';

export default {
    name: 'IOSScroll',
    props: {
        // 数据变化时需要重新计算滚动
        data: {
            type: Array,
            default: () => []
        },
        // 是否启用上拉加载
        pullUpLoad: {
            type: Boolean,
            default: false
        },
        // 是否启用下拉刷新
        pullDownRefresh: {
            type: Boolean,
            default: false
        }
    },
    emits: ['pullingDown', 'pullingUp'],
    setup(props, { emit }) {
        const scrollWrapper = ref(null);
        const bScroll = ref(null);
        const isRefreshing = ref(false);
        const isLoadingMore = ref(false);
        const isPullingDown = ref(false);
        const pullDownIcon = ref('fas fa-arrow-down');
        const pullDownText = ref('下拉刷新');
        const pullUpText = ref('上拉加载更多');
        const enablePullUp = ref(props.pullUpLoad);
        const scrollStyle = ref({});

        // 初始化滚动
        const initScroll = () => {
            if (!scrollWrapper.value) return;

            bScroll.value = new BScroll(scrollWrapper.value, {
                scrollY: true,
                click: true,
                tap: true,
                probeType: 3, // 实时监听滚动位置
                bounce: {
                    top: true,
                    bottom: true
                },
                // 如果启用下拉刷新，配置此项
                pullDownRefresh: props.pullDownRefresh ? {
                    threshold: 70,
                    stop: 50
                } : false,
                // 如果启用上拉加载，配置此项
                pullUpLoad: props.pullUpLoad ? {
                    threshold: -70
                } : false,
                preventDefaultException: {
                    tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|A)$/
                }
            });

            // 监听下拉刷新
            if (props.pullDownRefresh) {
                bScroll.value.on('pullingDown', () => {
                    isPullingDown.value = true;
                    pullDownIcon.value = 'fas fa-sync-alt';
                    pullDownText.value = '正在刷新...';
                    isRefreshing.value = true;
                    emit('pullingDown');
                });
            }

            // 监听上拉加载
            if (props.pullUpLoad) {
                bScroll.value.on('pullingUp', () => {
                    pullUpText.value = '正在加载...';
                    isLoadingMore.value = true;
                    emit('pullingUp');
                });
            }

            // iOS设备特殊优化
            if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
                document.body.style.webkitOverflowScrolling = 'touch';
            }
        };

        // 刷新滚动
        const refresh = () => {
            if (bScroll.value) {
                bScroll.value.refresh();
            }
        };

        // 完成下拉刷新
        const finishPullDown = (successText = '刷新成功') => {
            if (!bScroll.value) return;

            setTimeout(() => {
                isPullingDown.value = false;
                isRefreshing.value = false;
                pullDownIcon.value = 'fas fa-arrow-down';
                pullDownText.value = '下拉刷新';

                if (props.pullDownRefresh) {
                    bScroll.value.finishPullDown();
                    refresh();
                }

                if (successText) {
                    pullDownText.value = successText;
                    setTimeout(() => {
                        pullDownText.value = '下拉刷新';
                    }, 1000);
                }
            }, 300);
        };

        // 完成上拉加载
        const finishPullUp = (enableNext = true, successText = '加载成功') => {
            if (!bScroll.value) return;

            setTimeout(() => {
                isLoadingMore.value = false;
                pullUpText.value = '上拉加载更多';

                if (props.pullUpLoad) {
                    bScroll.value.finishPullUp();
                    enablePullUp.value = enableNext;
                    refresh();
                }

                if (successText) {
                    pullUpText.value = successText;
                    setTimeout(() => {
                        pullUpText.value = '上拉加载更多';
                    }, 1000);
                }
            }, 300);
        };

        // 滚动到指定位置
        const scrollTo = (x, y, time = 500) => {
            if (bScroll.value) {
                bScroll.value.scrollTo(x, y, time);
            }
        };

        onMounted(() => {
            initScroll();
        });

        onBeforeUnmount(() => {
            if (bScroll.value) {
                bScroll.value.destroy();
            }
            // 清理iOS优化
            if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
                document.body.style.webkitOverflowScrolling = '';
            }
        });

        return {
            scrollWrapper,
            scrollStyle,
            isRefreshing,
            isLoadingMore,
            isPullingDown,
            pullDownIcon,
            pullDownText,
            pullUpText,
            enablePullUp,
            finishPullDown,
            finishPullUp,
            refresh,
            scrollTo
        };
    }
};
</script>

<style scoped>
.ios-scroll {
    position: relative;
    height: 100%;
    overflow: hidden;
    -webkit-overflow-scrolling: touch;
}

.scroll-content {
    position: relative;
    z-index: 1;
}

.pull-down {
    position: absolute;
    top: -100px;
    left: 0;
    width: 100%;
    text-align: center;
    padding: 25px 0;
    color: #888;
    font-size: 15px;
    transition: all 0.3s;
}

.pull-down.active {
    transform: translateY(100px);
}

.pull-down-refresh {
    background: white;
    height: 50px;
    width: 50px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0 auto 10px;
    box-shadow: 0 3px 20px rgba(0, 0, 0, 0.08);
}

.pull-up {
    text-align: center;
    padding: 25px 0;
    color: #888;
    font-size: 15px;
}

.pull-up-refresh {
    background: rgba(42, 107, 240, 0.08);
    height: 45px;
    width: 45px;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 10px auto 0;
    transition: opacity 0.3s;
}

.loading {
    animation: rotate 1s linear infinite;
}

@keyframes rotate {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}
</style>